Config = require '../config'
Gzippo = require 'gzippo'
Path = require 'path'
Zlib = require 'zlib'
Crypto = require 'crypto'
Logger = require('log4js').getLogger()
if !Config.debug
  RedisClient = require '../models/redis_client'
  
#static files handle config#
staticPrefix = Config.server.staticPrefix
clientMaxAge = 60 * 60 * 1000
if Config.debug
  clientMaxAge = 1000
gzipOptions = 
  prefix : staticPrefix
  clientMaxAge : clientMaxAge
gzippoHandler = Gzippo.staticGzip Path.join(__dirname, '../', 'statics'), gzipOptions

#cache config#
TTL = 10 * 60
cacheKeyPrefix = 'vicanso_html_'

###*
 * [staticHandler description]
 * @param  {[type]}   req  [description]
 * @param  {[type]}   res  [description]
 * @param  {Function} next [description]
 * @return {[type]}        [description]
###
staticHandler = (req, res, next) ->
  gzippoHandler req, res, next

###*
 * [cacheHandler description]
 * @param  {[type]}   req  [description]
 * @param  {[type]}   res  [description]
 * @param  {Function} next [description]
 * @return {[type]}        [description]
###
cacheHandler = (req, res, next) ->
  if isUserInfoRequest req
    responseUserInfoRequest req, res
    return 
  if !isHTTPWebRequest(req) || !RedisClient
    next()
    return 
  key = getHashKey req
  RedisClient.hgetall key, (err, data) ->
    if err || !data
      next()
    else
      acceptEncoding = req.header 'accept-encoding'
      if data.gzip && acceptEncoding?.indexOf('gzip') != -1
        res.header 'Content-Encoding', 'gzip'
        res.header 'Content-Type', 'text/html'
        res.header 'Cache-Control', "public, max-age=#{TTL}"
        gzipData = new Buffer data.gzip, 'binary'
        res.send gzipData
      else if data.html
        res.header 'Content-Type', 'text/html'
        res.header 'Cache-Control', "public, max-age=#{TTL}"
        res.send data.html
      else
        next()

###*
 * [renderAndCache description]
 * @param  {[type]} req  [description]
 * @param  {[type]} res  [description]
 * @param  {[type]} view [description]
 * @param  {[type]} data [description]
 * @param  {[type]} ttl  [description]
 * @return {[type]}      [description]
###
renderAndCache = (req, res, view, data, ttl) ->
  if arguments.length < 4
    Logger.error 'renderAndCache function, the arguments is less than 4'
    res.send 'renderAndCache function, the arguments is less than 4', 504
    return 
  key = getHashKey req
  res.render view, data, (err, html) ->
    if err
      Logger.error err
      res.send err, 500
    else
        ttl ?= TTL
        setHTMLCache key, html, ttl
      res.header 'Content-Type', 'text/html'
      res.header 'Cache-Control', "public, max-age=#{TTL}"
      res.send html


isUserInfoRequest = (req) ->
  if req.url.indexOf('/static/ys/user_info.js') is 0
    return true
  return false

responseUserInfoRequest = (req, res) ->
  res.header 'Content-Type', 'application/javascript; charset=UTF-8'
  res.header 'Cache-Control', 'no-cache, no-store, max-age=0'
  host = 'http://' + req.headers?.host
  userInfo = 
    host : host
    paths :
      home : '/ys'
      table : '/ys/table'
  res.send 'var USER_INFO = ' + JSON.stringify userInfo

###*
 * [isHTTPWebRequest description]
 * @param  {[type]}  req [description]
 * @return {Boolean}     [description]
###
isHTTPWebRequest = (req) ->
  if req.xhr || !req.accepts 'html'
    return false
  return true

###*
 * [getHashKey description]
 * @param  {[type]} req [description]
 * @return {[type]}     [description]
###
getHashKey = (req) ->
  key = req.cacheKey
  if !key
    key = cacheKeyPrefix + Crypto.createHash('md5').update(req.url).digest 'base64'
    req.cacheKey = key
  return key
###*
 * [setHTMLCache description]
 * @param {[type]} key  [description]
 * @param {[type]} html [description]
 * @param {[type]} ttl  [description]
###
setHTMLCache = (key, html, ttl) ->
  if RedisClient?
    RedisClient.hmset key, 'html', html, (err) ->
      if !err
        RedisClient.expire key, ttl
        Zlib.gzip html, (err, data) ->
          if !err
            RedisClient.hmset key, 'gzip', data.toString 'binary'

module.exports =
  staticHandler : staticHandler
  cacheHandler : cacheHandler
  renderAndCache : renderAndCache